/**
 * @description 封装异步请求库
 */
import router from "@/router";
import store from "@/store";
import axios from "axios";

let AxiosInstance = axios.create({
  // baseURL: '/pangu',
  baseURL: "/wanxiang",
  timeout: 50000,
});

/**
 * 可以通过请求前的拦截实现--baseURL参数修改、实现请求头token注入、也可以实现token拦截(它是登录标识，那么如果一个用户连token都没有，那么不可以调用获取用户信息等这样的业务接口--实现请求权限拦截)
 * request是请求还没有发出去的拦截
 * use(onFulfilled?: (value: V) => V) use方法要求我们传递一个回调函数进去，然后函数有一个形参进来，要求我们返回一个传递进来的参数
 */
/**
 * 可以配置一个对象，这个对象的key就是代理地址，然后值为需要进行代理的url地址
 */
let proxyObj = {
  // "/wangxiang": ["/city/list"],
  "/wangxiang": ["/city/list"],
};
/**
 * 可以实现token通用注入控制，有些地址不要token，有些必须有token并且要注入
 * token在哪里？--vuex里边
 */
let noTokenUrl = [
  // 这里写不需要存储token的地址
  // 例如：'/user/login', '/user/validate/code', '/user/app/login', "/city/list"
  "/user/login",
];
AxiosInstance.interceptors.request.use((config) => {
  // if (config.url === "/city/list") {
  //     config.baseURL = '/wangxiang'
  // }
  // 按照请求地址来进行切换代理
  // for (let name in proxyObj) {
  //   let it = proxyObj[name];
  //   if (it.includes(config.url)) {
  //     config.baseURL = name;
  //     break;
  //   }
  // }

  // // 实现token拦截和注入
  if (noTokenUrl.includes(config.url)) {
    return config;
  } else {
    // 判断token是否存在，如果不存在--那么请求需要中断--因为axios是基于Promise封装的，所以可以返回一个错误的Promise(Promise.reject())就可以中断请求
    // let token = store.getters.token;
    let token = store.getters.token;
    // debugger
    if (!token) {
      return Promise.reject({
        code: 0,
        message: "前端没有token数据，你没有缓存",
      });
    } else {
      // config.headers.token = token

      config.headers["X-Token"] = token;
      return config;
    }
  }
});

/**
 * 响应拦截--对于跳过前端拦截，然后进行的响应处理
 * 可以实现token失效处理、验证请求是否安全
 * use(onFulfilled?: (value: AxiosResponse) => AxiosResponse | Promise)
 * use方法要求传递一个参数(数据类型为一个函数A)进去，函数A会入参一个响应对象B，可以对响应对象B进行处理，然后函数A要求返回一个响应对象B或则一个Promise对象
 */
AxiosInstance.interceptors.response.use((response) => {
  let { data } = response;
  if (
    data.code === 403 &&
    data.message === "Request information authentication failed."
  ) {
    alert("用户非法请求，请重新登录");
    router.push("/login");
    return Promise.reject({ code: 400, message: "用户非法请求，请重新登录" });
  } else {
    return response;
  }
});

/**
 * 异步请求方法
 * @param {string | {url: string,data: object, params: object, method: 'POST' | 'GET' | 'DELETE' | 'PUT' | 'PATCH'}}
 * @returns
 */
function ajax(req) {
  if (!req) throw new TypeError("请求参数必传");
  if (req.startsWith) {
    req = { url: req };
  }
  if (!req.url) throw new TypeError("url参数必传");
  // async + await 只能处理Promise.resolve（then结果）
  return new Promise((resolve) => {
    AxiosInstance.request({
      url: req.url,
      method: req.method || "POST",
      // 它是查询参数--链接在url地址传递的参数
      params: req.params || {},
      // 请求体参数
      data: req.data || {},
    })
      .then(({ data }) => {
        resolve(data);
      })
      .catch((e) => {
        resolve(e);
      });
  });
}

export default ajax;
